using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels;
using System.Net.Sockets;

namespace CVS
{
    public partial class P2PForm : Form
    {
        P2PClient _client;
        private List<string> _deleted_reps = new List<string>();
        int _checkout=0;
        bool _connected = false;
        string _repID;
        MainForm _mainForm;

        #region Constructors&Main

        public P2PForm(MainForm form, TcpChannel channel, string address)
        {
            InitializeComponent();

            _client = new P2PClient();
            _client.Initialize(channel, address);
            _mainForm = form;
        }

        #endregion

        #region Getters

        public string Address
        {
            get { return address.Text; }
        }

        #endregion

        #region ButtonClickMethods

        private void CreateRep_Click(object sender, EventArgs e)
        {
            if (_connected)
            {
                IRepositorio rep = _client.CreateRep(rep_name.Text);
                string[] rep_desc = { rep.Nome, rep.Id.ToString(), "X", "" };
                ListViewItem item = new ListViewItem(rep_desc);
                rep_list.Items.Add(item);

                MessageBox.Show("Repository created with id = " + rep.Id + ".");
                _checkout = 1;
            }
            else
            {
                MessageBox.Show("Please connect to a server to perform this operation.");
            }
        }

        private void checkin_rep_Click(object sender, EventArgs e)
        {
            if (_connected)
            {
                if (rep_list.SelectedItems.Count > 0)
                {
                    if (_client.CheckInRepository(rep_list.SelectedItems[0].SubItems[1].Text))
                    {
                        foreach (ListViewItem temp in rep_list.Items)
                        {
                            if (temp.SubItems[1].Text.CompareTo(rep_list.SelectedItems[0].SubItems[1].Text) == 0)
                            {
                                temp.SubItems[2].Text = "";
                                file_list.Items.Clear();
                            }
                        }

                        MessageBox.Show("Repository Checked-In");
                    }
                    else
                    {
                        MessageBox.Show("Unable to check-in. You have an older version of the repository.\n\nPlease press Check-Out before you press Check-In.");
                    }
                }
                else
                {
                    foreach (string id in _deleted_reps)
                    {
                        if (_client.DeleteRepository(id))
                        {
                            MessageBox.Show("Permanent deletion of repository - " + id + " - at server level.");
                        }
                    }
                    _deleted_reps.Clear();
                }
            }
            else
            {
                MessageBox.Show("Please connect to a server to perform this operation.");
            }
        }

        private void CheckoutRep_Click(object sender, EventArgs e)
        {
            if (_connected)
            {
                IRepositorio rep = _client.CheckoutRep(rep_id.Text);
                if (rep != null)
                {
                    foreach (ListViewItem temp in rep_list.Items)
                    {
                        if (temp.SubItems[1].Text.CompareTo(rep.Id) == 0)
                        {
                            rep_list.Items.Remove(temp);
                            break;
                        }
                    }

                    string[] rep_desc = { rep.Nome, rep.Id.ToString(), "", "" };
                    ListViewItem item = new ListViewItem(rep_desc);
                    rep_list.Items.Add(item);
                    _checkout = 1;
                    MessageBox.Show("Check-out sucessful.");
                }
                else
                {
                    MessageBox.Show("Check-out failed: no such id.");
                }
            }
            else
            {
                MessageBox.Show("Please connect to a server to perform this operation.");
            }

        }

        private void delete_rep_Click(object sender, EventArgs e)
        {
            if (rep_list.SelectedItems.Count > 0)
            {
                _deleted_reps.Add(rep_list.SelectedItems[0].SubItems[1].Text);
                rep_list.Items.Remove(rep_list.SelectedItems[0]);
            }
        }

        private void CreateFile_Click(object sender, EventArgs e)
        {
            if (rep_list.SelectedItems.Count == 0)
            {
                MessageBox.Show("Please select a repository first.");
            }
            else
            {
                _client.CreateFile(file_name.Text, rep_list.SelectedItems[0].SubItems[1].Text);
                string[] file_desc = { file_name.Text, "X", "" };
                ListViewItem item = new ListViewItem(file_desc);
                file_list.Items.Add(item);

                rep_list.SelectedItems[0].SubItems[2].Text = "X";
            }
        }

        private void DeleteFile_Click(object sender, EventArgs e)
        {
            if ((rep_list.SelectedItems.Count > 0) && (file_list.SelectedItems.Count > 0))
            {
                _client.DeleteFile(rep_list.SelectedItems[0].SubItems[1].Text,
                                         file_list.SelectedItems[0].SubItems[0].Text, _checkout);
                file_list.Items.Remove(file_list.SelectedItems[0]);
                MessageBox.Show("File deleted.");
            }
            else
                if ((_checkout == 0) && (file_list.SelectedItems.Count > 0))
                {
                    _client.DeleteFile(_repID, file_list.SelectedItems[0].SubItems[0].Text, _checkout);
                    file_list.Items.Remove(file_list.SelectedItems[0]);
                    MessageBox.Show("File deleted.");
                }   
        }

        private void list_files_Click(object sender, EventArgs e)
        {
            if (_connected)
            {
                _checkout = 0;
                _repID = rep_id.Text;
                string filelist = _client.ListFiles(rep_id.Text);

                if (filelist != null)
                {
                    string[] files = filelist.Split('#');
                    string[] file_content;

                    file_list.Items.Clear();

                    for (int i = 0; i < files.Length; i++)
                    {
                        file_content = files[i].Split('@');
                        if (file_content.Length >= 2)
                        {
                            string[] file_desc = { file_content[0], "", file_content[1] };
                            ListViewItem item = new ListViewItem(file_desc);
                            file_list.Items.Add(item);
                        }
                    }
                }
                else
                {
                    MessageBox.Show("No repository with given id found.");
                }
            }
            else
            {
                MessageBox.Show("Please connect to a server to perform this operation.");
            }
            
        }

        private void Connect_Click(object sender, EventArgs e)
        {
            //Informs the client of the current server address to connect
            string newAddress = _client.Connect(address.Text);

            if (newAddress != null){
                MessageBox.Show("Connected to: " + newAddress);

                _connected = true;

                //Create finger table
                _client.CreateFingerTable();

                List<string> fingers = _client.RetrieveFingerTable();
                finger_table.Items.Clear();
                foreach (string finger in fingers)
                {
                    finger_table.Items.Add(finger);
                }

                //Transfer data to this new client if necessary
                _client.GetSucessorData();

                string info = _client.RetrieveRingInformation();
                string[] addresses = info.Split('#');

                p2p_window.Items.Add("Node: " + addresses[0]);
                p2p_window.Items.Add("Sucessor: " + addresses[1]);
                p2p_window.Items.Add("Predecessor: " + addresses[2]);
                p2p_window.Items.Add("Node Key: " + addresses[3]);
            }
            else
            {
                MessageBox.Show("Unknown address.");
            }

        }

        private void Disconnect_Click(object sender, EventArgs e)
        {
            if (_connected)
            {
                _client.Disconnect();
                MessageBox.Show("Client disconnected. All data transfered to its sucessor.");

                this.Close();
            }
            else
            {
                MessageBox.Show("Client disconnected.");
                this.Close();
            }
        }

        private void refresh_Click(object sender, EventArgs e)
        {
            List<string> fingers = _client.RetrieveFingerTable();
            finger_table.Items.Clear();
            foreach (string finger in fingers)
            {
                finger_table.Items.Add(finger);
            }

            p2p_window.Items.Clear();
            string info = _client.RetrieveRingInformation();
            string[] addresses = info.Split('#');

            p2p_window.Items.Add("Node: " + addresses[0]);
            p2p_window.Items.Add("Sucessor: " + addresses[1]);
            p2p_window.Items.Add("Predecessor: " + addresses[2]);
            p2p_window.Items.Add("Node Key: " + addresses[3]);

            info = _client.Print();
            string[] repositories = info.Split('#');

            for (int i = 0; i < repositories.Length; i++)
            {
                p2p_window.Items.Add(repositories[i]);
            }
        }

        private void Load_rep_Click(object sender, EventArgs e)
        {
            _client.Load(path.Text);
        }

        #endregion

        #region EventTriggeredMethods

        private void ShowRepContent(object sender, EventArgs e)
        {
            List<IFicheiro> files = _client.ShowRepContent(rep_list.SelectedItems[0].SubItems[1].Text);

            file_list.Items.Clear();
            foreach (IFicheiro file in files)
            {
                if (file.Alterado == true)
                {
                    string[] file_desc = { file.Nome, "X", file.Conteudo.Length.ToString() };
                    ListViewItem item = new ListViewItem(file_desc);
                    file_list.Items.Add(item);
                }
                else
                {
                    string[] file_desc = { file.Nome, "", file.Conteudo.Length.ToString() };
                    ListViewItem item = new ListViewItem(file_desc);
                    file_list.Items.Add(item);
                }
                
            }
        }

        private void ShowFileContent(object sender, EventArgs e)
        {
            if (_checkout == 1)
            {
                if ((rep_list.SelectedItems.Count > 0) && (file_list.SelectedItems.Count > 0))
                {
                    string content = _client.ShowFileContent(rep_list.SelectedItems[0].SubItems[1].Text,
                                                         file_list.SelectedItems[0].SubItems[0].Text);

                    edit_box.Text = content;
                    edit_box.Enabled = true;
                }
                else {
                    MessageBox.Show("Please select the repository as well.");
                }
            }
            else
            {
                MessageBox.Show("Please press Check-Out first.");
            }
        }

        private void SaveFile(object sender, EventArgs e)
        {
            if (_checkout == 1)
            {
                if ((rep_list.SelectedItems.Count > 0) && (file_list.SelectedItems.Count > 0))
                {
                    if (_client.SaveFile(rep_list.SelectedItems[0].SubItems[1].Text,
                                         file_list.SelectedItems[0].SubItems[0].Text,
                                         edit_box.Text) == true)
                    {
                        file_list.SelectedItems[0].SubItems[1].Text = "X";

                        rep_list.SelectedItems[0].SubItems[2].Text = "X";
                    }
                }

                edit_box.Text = "";
                edit_box.Enabled = false;
            }
            else {
                MessageBox.Show("Please press Check-Out first");
            }
        }

        private void DisableEditor(object sender, EventArgs e)
        {
            if (file_list.SelectedItems.Count == 0)
            {
                edit_box.Text = "";
                edit_box.Enabled = false;
            }
        }

        private void server_mode_CheckedChanged(object sender, EventArgs e)
        {
            if (server_mode.Checked == true)
            {
                this.Hide();
                p2p_mode.Checked = true;
                server_mode.Checked = false;
                _mainForm.Show();
            }
        }

        #endregion 
 
    }
}
